home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / fish / 676-700 / 676 / fbm / fbm10ami.zoo / gif2fbm.c < prev    next >
C/C++ Source or Header  |  1991-06-11  |  11KB  |  494 lines

  1. /* GIF2FBM.c -- Convert GIF to FBM acting as a filter */
  2. /* GIF-decompession-routine partially taken from xgif.c */
  3. /* Works also for interlaced GIF-Files */
  4. /* Compilation: SAS/C 5.10:          "LC -Lcdm -O -cr -v -w gif2hl.c" */
  5. /*              SYS V Unix compiler: "cc -o gif2fbm -DSYSV -O gif2fbm.c" */
  6.  
  7. #include <stdio.h>
  8.  
  9. #define MAX(a,b)    ((a)>(b)?(a):(b))
  10. #define MIN(a,b)    ((a)<(b)?(a):(b))
  11. #define ABS(x)      ((x<0)?(-(x)):(x))
  12.  
  13. #ifdef SYSV
  14. #include <malloc.h>
  15. #endif
  16.  
  17. #ifdef AZTEC_C
  18. #include <functions.h>
  19. #include <stdlib.h>
  20. #endif
  21.  
  22. #ifdef LATTICE
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #define ANSI_C
  26. #endif
  27.  
  28. typedef unsigned char UBYTE;
  29. typedef unsigned short UWORD;
  30. typedef unsigned long ULONG;
  31.  
  32. #define ILL_PAR 102
  33. #define NO_MEM 100
  34. #define NOT_INP 104
  35. #define NOT_OUT 105
  36.  
  37. /* #define DEBUG */
  38.  
  39. #ifdef ANSI_C
  40. UWORD fget16(FILE *);
  41. void AddToPixel(UBYTE);
  42. void WriteFBM(UWORD, UWORD);
  43. UBYTE getubyte();
  44. UWORD getbits(short);
  45. #endif
  46.  
  47. /* Globale Variablen */
  48.  
  49. static UBYTE *PixelBuffer[2048];
  50. static char *Cregs;
  51.  
  52. static UWORD Prefix[4096], Suffix[4096];
  53. static UWORD OutCode[1025];
  54.  
  55. char Interlace;
  56. unsigned long TCounter = 0;
  57. char FileTerminate = 0;
  58.  
  59. static UWORD XC = 0,
  60.     YC = 0,
  61.     Pass = 0,
  62.     OutCount = 0,
  63.     RWidth, RHeight,
  64.     Width, Height,
  65.     LeftOfs, TopOfs,
  66.     CodeSize;
  67. static UBYTE background;
  68.  
  69. static float aspect = 1.0;
  70.  
  71. # define FBM_MAX_TITLE        80        /* For title and credits */
  72.  
  73. # define BLACK            0        /* For 8bit files */
  74. # define WHITE            255        /* For 8bit files */
  75. # define BYTE            256        /* For 8bit files */
  76.  
  77. # define BLANKS        "                                             "
  78.  
  79. # define FBM_MAGIC    "%bitmap"
  80.  
  81. /* FBM bitmap headers in files (null terminated 12 character ascii strings) */
  82. typedef struct fbm_filehdr_struct {
  83.     char    magic[8];        /* 8 bytes FBM_MAGIC number */
  84.     char    cols[8];        /* Width in pixels */
  85.     char    rows[8];        /* Height in pixels */
  86.     char    planes[8];        /* Depth (1 for B+W, 3 for RGB) */
  87.     char    bits[8];        /* Bits per pixel */
  88.     char    physbits[8];        /* Bits to store each pixel */
  89.     char    rowlen[12];        /* Length of a row in bytes */
  90.     char    plnlen[12];        /* Length of a plane in bytes */
  91.     char    clrlen[12];        /* Length of colormap in bytes */
  92.     char    aspect[12];        /* ratio of Y to X of one pixel */
  93.     char    title[FBM_MAX_TITLE];    /* Null terminated title */
  94.     char    credits[FBM_MAX_TITLE];    /* Null terminated credits */
  95. } FBMFILEHDR;
  96.  
  97. static UWORD fget16(fp)
  98. register FILE *fp;
  99. {
  100.   register UBYTE b1,b2;
  101.   b1=getc(fp);
  102.   b2=getc(fp);
  103.   return((UWORD)b1 | ((UWORD)b2 << 8));
  104. }
  105.  
  106. /* getubyte: get a byte from blocked file */
  107. /* returns byte in <ch> and a return value of 0 in <FileTerminate> if ok */
  108. /* uses global variables <count>, <FileTerminate> and <stdin> */
  109.  
  110. short count = 0;
  111.  
  112. UBYTE getubyte()
  113. {
  114.   register UBYTE ch;
  115.  
  116.   if (feof(stdin)) {
  117.     FileTerminate=!0;
  118.     return(0);
  119.   };
  120.   if (count != 0) {
  121.     ch = getc(stdin);
  122.     count--;
  123.   }
  124.   else {
  125.     count = getc(stdin);
  126.     if (count==0) {
  127.       FileTerminate=!0;
  128.       return(0);
  129.     };
  130.     ch = getc(stdin);
  131.     count--;
  132.   };
  133.   return(ch);
  134. }
  135.  
  136. short bitcount = 0;
  137. UWORD restbits = 0;
  138.  
  139. UWORD getbits(bits)
  140. register short bits;
  141. {
  142.   register UWORD w;
  143.   register UBYTE mask;
  144.   register short shift;
  145.   register UBYTE c;
  146.  
  147.   w = 0;
  148.   shift = 0;
  149.   while (bits != 0) {
  150.     if (bitcount==0) {
  151.       c=getubyte();
  152.       if (FileTerminate) {
  153.         return(w);
  154.       };
  155.       if (bits>=8) {
  156.         w |= ((UWORD)c << shift);
  157.         bits -= 8;
  158.         shift += 8;
  159.         restbits = 0;
  160.       }
  161.       else {
  162.         mask = 0xff;
  163.         mask >>= (8-bits);
  164.         w |= ((c & mask) << shift);
  165.         restbits = c >> bits;
  166.         bitcount = 8-bits;
  167.         shift += bits;
  168.         bits = 0;
  169.       };
  170.     }
  171.     else { /* bitcount > 0 */
  172.       if (bits>=bitcount) {
  173.         w |= (restbits << shift);
  174.         bits -= bitcount;
  175.         shift += bitcount;
  176.         bitcount=0;
  177.         restbits = 0;
  178.       }
  179.       else { /* bits < bitcount */
  180.         mask = 0xff;
  181.         mask >>= (8-bits);
  182.         w |= ((restbits & mask) << shift);
  183.         restbits >>= bits;
  184.         bitcount -= bits;
  185.         shift += bits;
  186.         bits = 0;
  187.       };
  188.     };
  189.   }; /* while */
  190. #ifdef DEBUG
  191.   printf(" |%u| ",(unsigned)w);
  192. #endif
  193.   return(w);
  194. }
  195.  
  196. void AddToPixel(Index)
  197. UBYTE Index;
  198. {
  199.   register UBYTE *ptr;
  200.  
  201. #ifdef DEBUG
  202.   printf(" {%x} ",(unsigned)Index);
  203. #endif
  204.   if (YC < Height) {
  205.     ptr = PixelBuffer[YC];
  206.     ptr += (unsigned long)XC;
  207.     *ptr = Index;
  208.     if (++XC == Width) {
  209.       XC=0;
  210.       if (!Interlace) YC++;
  211.       else {
  212.         switch(Pass) {
  213.           case 0:
  214.             YC += 8;
  215.             if (YC >= Height) {
  216.               Pass++;
  217.               YC=4;
  218.             };
  219.             break;
  220.           case 1:
  221.             YC += 8;
  222.             if (YC >= Height) {
  223.               Pass++;
  224.               YC=2;
  225.             };
  226.             break;
  227.           case 2:
  228.             YC += 4;
  229.             if (YC >= Height) {
  230.               Pass++;
  231.               YC=1;
  232.             };
  233.             break;
  234.           case 3:
  235.             YC += 2;
  236.             break;
  237.           default:
  238.           break;
  239.         };
  240.       };
  241.     };
  242.   };
  243. }
  244.  
  245. /* Write a 24-bit file for FBM */
  246. void WriteFBM(height,width)
  247. UWORD height,width;
  248. {
  249.   register UWORD i,j;
  250.   register UBYTE *ptr;
  251.   UBYTE *colptr;
  252.   UWORD rowlen;
  253.   FBMFILEHDR *fbm_hdr;
  254.  
  255.   rowlen = 2 * ((width * 8 + 15) / 16);
  256.  
  257.   if ((fbm_hdr=malloc(sizeof(FBMFILEHDR))) == NULL) {
  258.     fprintf(stderr,"Not enough memory for malloc()\n");
  259.     exit(NO_MEM);
  260.   };
  261.  
  262.   strncpy(fbm_hdr->magic,FBM_MAGIC,8);
  263.   sprintf(fbm_hdr->cols,"%7u",(unsigned)width);
  264.   sprintf(fbm_hdr->rows,"%7u",(unsigned)height);
  265.   sprintf(fbm_hdr->planes,"%7u",3);
  266.   sprintf(fbm_hdr->bits,"%7u",8);
  267.   sprintf(fbm_hdr->physbits,"%7u",8);
  268.  
  269.   sprintf(fbm_hdr->rowlen,"%11u",(unsigned)rowlen);
  270.   sprintf(fbm_hdr->plnlen,"%11lu",(ULONG)rowlen*(ULONG)height);
  271.   sprintf(fbm_hdr->clrlen,"%11u",0);
  272.   sprintf(fbm_hdr->aspect,"%11.6f",aspect);
  273.   strncpy(fbm_hdr->title,"",80);
  274.   strncpy(fbm_hdr->credits,"",80);
  275.   fwrite(fbm_hdr,1,sizeof(FBMFILEHDR),stdout);
  276.   free(fbm_hdr);
  277.  
  278.   /* Write RED plane */
  279.   for (i=0; i<height; i++) {
  280.     ptr = PixelBuffer[i];
  281.     for (j=0; j<width; j++) {
  282.       colptr=Cregs + (ULONG)(*(ptr+(ULONG)j) * 3);
  283.       putchar(*colptr);
  284.     };
  285.     for (j=width; j<rowlen; j++) putchar('\0');
  286.   };
  287.   /* Write GREEN plane */
  288.   for (i=0; i<height; i++) {
  289.     ptr = PixelBuffer[i];
  290.     for (j=0; j<width; j++) {
  291.       colptr=Cregs + (ULONG)(*(ptr+(ULONG)j) * 3 + 1);
  292.       putchar(*colptr);
  293.     };
  294.     for (j=width; j<rowlen; j++) putchar('\0');
  295.   };
  296.   /* Write BLUE plane */
  297.   for (i=0; i<height; i++) {
  298.     ptr = PixelBuffer[i];
  299.     for (j=0; j<width; j++) {
  300.       colptr=Cregs + (ULONG)(*(ptr+(ULONG)j) * 3 + 2);
  301.       putchar(*colptr);
  302.     };
  303.     for (j=width; j<rowlen; j++) putchar('\0');
  304.   };
  305. }
  306.  
  307. main()
  308. {
  309.   UWORD Colors;
  310.   UWORD sWidth, sHeight;
  311.   UBYTE gFlags;
  312.   UWORD iWidth, iHeight, iLeft, iTop;
  313.   UWORD iCol,
  314.     Code,
  315.     MaxCode,
  316.     ClearCode,
  317.     EOFCode,
  318.     OldCode,
  319.     InCode,
  320.     FirstFree,
  321.     FinChar,
  322.     BitMask,
  323.     InitCodeSize,
  324.     BitsPerPixel;
  325.   UBYTE iFlags;
  326.   UBYTE c;
  327.   UBYTE AspByte; /* Aspect Ratio information */
  328.   int n;
  329.   char IDbuffer[6];
  330.   register UWORD FreeCode, CurCode;
  331.   register short i;
  332.  
  333.   n=fread(IDbuffer,6,1,stdin);
  334.   if (strncmp(IDbuffer,"GIF87a",6)!=0) {
  335.     fprintf(stderr,"GIF87a - ID not found\n");
  336.     exit(30);
  337.   };
  338.   sWidth = Width = fget16(stdin);
  339.   sHeight = Height = fget16(stdin);
  340.   gFlags = (UBYTE)getc(stdin);
  341.   background = (UBYTE)getc(stdin);
  342.   AspByte = (UBYTE)getc(stdin);
  343.   if (AspByte!=0) aspect = ((float)((UWORD)AspByte + 15)) / 64.0;
  344.  
  345.   BitsPerPixel = (gFlags & 0x07) + 1;
  346.  
  347.   Colors= 1 << BitsPerPixel;
  348.   if ((Cregs = malloc(3*(unsigned)Colors)) == NULL) {
  349.     fprintf(stderr,"not enough memory for malloc()\n");
  350.     exit(50);
  351.   };
  352.   n=fread(Cregs,(int)Colors,3,stdin);
  353.  
  354.   if ((c=getc(stdin))==0x2c) { /* process Image separator */
  355.     iLeft = fget16(stdin);
  356.     iTop = fget16(stdin);
  357.     iWidth = Width = fget16(stdin);
  358.     iHeight = Height = fget16(stdin);
  359.     iFlags = getc(stdin);
  360.     Interlace = (iFlags & 0x40);
  361.     if (iFlags & 0x80) {
  362.       iCol = (iFlags & 0x07) + 1;
  363.       BitsPerPixel = iCol;
  364.       Colors = iCol;
  365.     };
  366.   }
  367.   else {
  368.     fprintf(stderr,"No Image separator found\n");
  369.     exit(30);
  370.   };
  371.  
  372.   if (AspByte == 0) {
  373.     if ((Width==320) && (Height==200)) aspect=1.2;
  374.     else if ((Width==640) && (Height==480)) aspect=1.0;
  375.     else if ((Width==640) && (Height==350)) aspect=1.37142857;
  376.     else aspect = 1.0;
  377.   };
  378.  
  379.   if (Height>2048) {
  380.     fprintf(stderr,"Image too large (Height > 2048)\n");
  381.     exit(40);
  382.   };
  383.  
  384.   for (i=0; i<Height; i++) {
  385.     if ((PixelBuffer[i]=malloc((unsigned)Width))==NULL) {
  386.       fprintf(stderr,"not enough memory for the pixelbuffer\n");
  387.       exit(50);
  388.     };
  389.     setmem(PixelBuffer[i],(unsigned)Width,0);
  390.   };
  391.  
  392.   for (i=0; i<4096; i++) Prefix[i]=Suffix[i]=0;
  393.  
  394.   fprintf(stderr,"Reading %u*%u Image\n",(unsigned)Width,(unsigned)Height);
  395.  
  396.   /* Rasterdaten lesen -- Beginn */
  397.  
  398.   BitMask = Colors - 1;
  399. #ifdef DEBUG
  400.   printf("BitMask=%u\n",(unsigned)BitMask);
  401. #endif
  402.   CodeSize = getc(stdin);
  403.   ClearCode = (1 << CodeSize);
  404.   EOFCode = ClearCode + 1;
  405.   FreeCode = FirstFree = ClearCode + 2;
  406.  
  407.   CodeSize++;
  408.   InitCodeSize = CodeSize;
  409.   MaxCode = (1 << CodeSize);
  410. #ifdef DEBUG
  411.   printf("CodeSize=%u MaxCode=%u\n",(unsigned)CodeSize,(unsigned)MaxCode);
  412. #endif
  413.  
  414.   InCode = 0;
  415.   /* Decompress */
  416.  
  417.   Code = getbits(CodeSize);
  418.   if (FileTerminate) {
  419.     goto Corrupt_GIF;
  420.   };    
  421.   while (Code != EOFCode) {
  422.     if (Code == ClearCode) {
  423.       CodeSize = InitCodeSize;
  424.       MaxCode = (1 << CodeSize);
  425.       FreeCode = FirstFree;
  426.       CurCode = OldCode = Code = getbits(CodeSize);
  427.       if (FileTerminate) {
  428.         goto Corrupt_GIF;
  429.       };    
  430.       FinChar = CurCode & BitMask;
  431.       AddToPixel((UBYTE)FinChar);
  432.       TCounter++;
  433.     }
  434.     else { /* Normal Data */
  435.       CurCode = InCode = Code;
  436. #ifdef DEBUG
  437.       printf("[%x]\n",(unsigned)CurCode);
  438. #endif
  439.       if (CurCode >= FreeCode) {
  440.         CurCode = OldCode;
  441.         OutCode[OutCount++] = FinChar;
  442.         TCounter++;
  443.       };
  444.  
  445.       while (CurCode > BitMask) {
  446. #ifdef DEBUG
  447.         printf("=%x=\n",(unsigned)CurCode);
  448. #endif
  449.         if (OutCount > 1024) {
  450. Corrupt_GIF:
  451.  
  452. #ifdef DEBUG
  453.           printf("BitMask=%u\n",(unsigned)BitMask);
  454. #endif
  455.           goto save_image;
  456.         };
  457.         TCounter++;
  458.         OutCode[OutCount++] = Suffix[CurCode];
  459.         CurCode = Prefix[CurCode];
  460.       };
  461.       FinChar = CurCode & BitMask;
  462.       TCounter++;
  463.       OutCode[OutCount++] = FinChar;
  464.  
  465.       for (i = OutCount-1; i>=0; i--) AddToPixel((UBYTE)OutCode[i]);
  466.       OutCount = 0;
  467.  
  468. #ifdef DEBUG
  469.       printf(" F(%d)=(%xP|%xS) ",FreeCode,OldCode,FinChar);
  470. #endif
  471.       Prefix[FreeCode] = OldCode;
  472.       Suffix[FreeCode] = FinChar;
  473.       OldCode = InCode;
  474.  
  475.       FreeCode++;
  476.       if (FreeCode >= MaxCode) {
  477.         if (CodeSize < 12) {
  478.           CodeSize++;
  479.           MaxCode <<= 1;
  480.         };
  481.       };
  482.     }; /* else */
  483.     Code = getbits(CodeSize);
  484.     if (FileTerminate) {
  485.       goto Corrupt_GIF;
  486.     };    
  487.   }; /* while */
  488. save_image:
  489.  
  490.   fprintf(stderr,"Writing %u*%u FBM-Bitmap\n",(unsigned)Width,(unsigned)Height);
  491.   WriteFBM(Height,Width);
  492.   for (i=0; i<Height; i++) free(PixelBuffer[i]);
  493. }
  494.